s
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            overflow: hidden;
        }

        html,
        body {
            width: 100%;
            height: 100%;
            background-color: #000;
        }

        .bg {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: #171717;
        }

        .bg::before {
            content: '';
            position: absolute;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            background-image: url(./xingkong.jpg);
            background-position: center center;
            background-size: cover;
            opacity: 0.5;
        }


        #my-canvas {
            position: relative;
            z-index: 10;
        }
    </style>
</head>

<body>
    <div class="bg"></div>
    <canvas id="my-canvas"></canvas>
    <script>
        class Effect {
            constructor(options) {
                const { id = 'canvas' } = options;
                this.canvas = document.getElementById(id);
                this.ctx = this.canvas.getContext('2d');
                this.config = {
                    r: 2,
                    color: 'rgba(255,255,255,0.8)',
                    xvRange: [-2, 2],
                    yvRange: [-2, 2],
                    scaleRange: [0.5, 2],
                    count: 100,
                    maxDistace: 150,
                    ...options
                }
                this.dots = [];// 点的数组
                // 鼠标是否在画布上
                this.isIn = false;
                // 鼠标的坐标
                this.aMouse = {
                    x: 0,
                    y: 0,
                    r: 3
                }
                this.mouseDot = null;
                this.init()
            }
            // 初始化
            init() {
                this.setSize();
                this.createDot(this.config.count);
                this.draw();
                this.canvas.addEventListener('mousemove', this.mouseMove.bind(this));
                this.canvas.addEventListener('mouseover', () => {
                    // console.log(this.mouseDot)
                    this.isIn = true;
                });
                this.canvas.addEventListener('mouseleave', () => {
                    // console.log(this.mouseDot)
                    // x	要清除的矩形左上角的 x 坐标
                    // y	要清除的矩形左上角的 y 坐标
                    // width	要清除的矩形的宽度，以像素计
                    // height	要清除的矩形的高度，以像素计
                    this.ctx.clearRect(this.mouseDot.x, this.mouseDot.y, this.aMouse.r, this.aMouse.r);
                    this.isIn = false;
                });
            }
            // 设置画布的宽高
            setSize() {
                this.canvas.width = window.innerWidth;
                this.canvas.height = window.innerHeight;
            }
            resetXY() {
                this.dots.forEach(item => {
                    if (item.x < item.r || item.x > window.innerWidth - item.r) {
                        item.x = utils.random(this.config.r, window.innerWidth - this.config.r);
                    }
                    if (item.y < item.r || item.y > window.innerHeight - item.r) {
                        item.y = utils.random(this.config.r, window.innerHeight - this.config.r);
                    }
                })
            }
            /**
             *  通过类Dot的draw创造点的数组
             */
            createDot(count = 100) {
                while (count--) {
                    const dot = new Dot({
                        x: utils.random(this.config.r, window.innerWidth - this.config.r),
                        y: utils.random(this.config.r, window.innerHeight - this.config.r),
                        xv: utils.random(...this.config.xvRange),
                        yv: utils.random(...this.config.yvRange),
                        color: this.config.color,
                        r: this.config.r,
                        scale: utils.random(...this.config.scaleRange)
                    })
                    this.dots.push(dot)
                }
            }
            draw() {
                // 先清空上次绘画内容
                this.ctx.clearRect(0, 0, window.innerWidth, window.innerHeight);
                this.dots.forEach(item => {
                    item.draw(this.ctx)
                })
                // 两点之间的连线
                for (let i = 0; i < this.dots.length; i++) {
                    for (let j = 0; j < this.dots.length; j++) {
                        this.createLine(this.dots[i], this.dots[j])
                    }
                }
                // 回调函数 在上次(上一帧)绘画完成之后自动执行；
                // 理解成setTimeout，setInterval死递归
                // bind保持一个实例
                window.requestAnimationFrame(this.moveDot.bind(this))
                // 鼠标在画布内才创建一个跟随鼠标的点
                if (this.isIn) {
                    this.drawMouseDot();
                }
            }
            moveDot() {
                this.dots.forEach(item => {
                    // 改变坐标
                    item.x += item.xv;
                    item.y += item.yv;
                    // 变了之后再进行边界判断
                    if (item.x < item.r || item.x > window.innerWidth - item.r) {
                        item.xv *= -1;
                    }
                    if (item.y < item.r || item.y > window.innerHeight - item.r) {
                        item.yv *= -1;
                    }
                })
                // 再次绘画更新的点
                this.draw()
            }
            // 移动时记录坐标
            mouseMove(e) {
                this.aMouse.x = e.pageX;
                this.aMouse.y = e.pageY;
            }
            drawMouseDot() {
                this.mouseDot = new Dot({
                    x: this.aMouse.x,
                    y: this.aMouse.y,
                    xv: 0,
                    yv: 0,
                    color: this.config.color,
                    r: 3,
                    scale: 2
                })
                // 创造一个跟随鼠标的点
                this.mouseDot.draw(this.ctx);
                for (let i = 0; i < this.dots.length; i++) {
                    this.createLine(this.dots[i], this.aMouse)
                }
            }
            createLine(prev, next) {
                // 勾股定理获取两点之间的距离：不需要考虑前后关系，都是平方和
                let distance = Math.sqrt(Math.pow(prev.x - next.x, 2) + Math.pow(prev.y - next.y, 2))
                if (distance < this.config.maxDistace) {
                    // border的颜色：实现距离短的线清晰，距离远的线透明度高
                    this.ctx.strokeStyle = this.config.color.replace(/,(\d\.*\d*)\)/, (a, b) => {
                        return ',' + b * (1 - distance / this.config.maxDistace) + ')'
                    })
                    this.ctx.beginPath();// 固定api：起笔
                    this.ctx.moveTo(prev.x, prev.y);// 固定api：起点
                    this.ctx.lineTo(next.x, next.y);// 固定api：终点
                    this.ctx.closePath();// 固定api：闭合
                    this.ctx.stroke()
                }
            }
        }

        // 创造点/粒子
        class Dot {
            constructor(options) {
                const { x, y, xv, yv, color, r, scale } = options;
                // 位置
                this.x = x;
                this.y = y;
                // 速度
                this.xv = xv;
                this.yv = yv;
                // 颜色
                this.color = color;
                // 大小
                this.r = r;
                this.scale = scale;
            }
            draw(ctx) {
                ctx.beginPath();// 固定api：起笔
                ctx.fillStyle = this.color;// 固定api：backgroud
                ctx.strokeStyle = this.color;// 固定api：border
                ctx.arc(this.x, this.y, this.r * this.scale, 0, Math.PI * 2);// 固定api：画圆（位置、半径、0~2π）
                ctx.closePath();// 固定api：闭合
                ctx.fill();// 固定api：填充
            }
        }
        var utils = {
            random(min, max) {
                // max=2;min=1; 0+1~1+1
                return Math.random() * (max - min) + min
            }
        }




        const plugins = new Effect({
            id: 'my-canvas'
        })
        window.onresize = function (e) {
            //  $(window).width();  
            console.log(e)
            plugins.setSize()
            plugins.resetXY()
        }
        // var offsetWid = document.documentElement.clientWidth;
        // var offsetHei = document.documentElement.clientHeight;

        // if (/(Android)/i.test(navigator.userAgent)){     // 判断是否为Android手机
        //     offsetWid = screen.width;
        //     offsetHei = screen.height;
        // }else if(/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)){  // 判断是否为苹果手机
        //     offsetWid=document.documentElement.clientWidth;
        //     offsetHei=document.documentElement.clientHeight;
        // }
    </script>
</body>

</html>